#!/usr/bin/env python3
# -*- Mode: python -*-

# Extract various information from dichotomous keys in YAMAL format.
# Copyright (C) 2014 P. Cherepanov and E. Batyrova
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys, os, getopt,re

mode = "chars"

lead_sep=re.compile("[ \.()]+")

def usage(n):
    print("yamal [OPTIONS] FILE")
    exit(n)

def error(msg):
    print(msg)
    exit(1)


aux_attrs = {
  "yes" : 0,
  "no"  : 0,
  "Lead" : 0
}

def traverse(pool, key, bag):
    it = pool[key]
    if "yes" in it:
        traverse(pool, it["yes"], bag + list(it.items()))
        if "no" in it:
            traverse(pool, it["no"], bag)
    else:
        attrs = sorted(bag+list(it.items()))
        for a in attrs:
          if not a[0] in aux_attrs:
              print(a)
        
        print("--------------------------------------------------------")

def main():
    global mode
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hvcm:", ["help", "version", "chars","mode="])
    except getopt.GetoptError:
        usage(2)

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage(0)
        elif opt in ('-v', '--version'):
            print("1.0")
            exit(0)
        elif opt in ('-c', '--chars'):
            mode = "chars"
        elif opt in ('-m', '--mode'):
            if arg in ("chars", "pages"):
                mode = arg
            else:
                error("Unknown mode="+arg)

    if len(args) != 1:
        error("Wrong number of arguments.")

    src = open(args[0])
    entry = {}
    keybook = []
    acc = ""
    taxon = ""
    eof = False
    while not eof:
        for s in src:
            s = s.strip()
            if s and s[0] == "#":
                continue
            if s and s[-1] == '\\':
                acc += s[:-1]
                continue
            s = acc + s
            acc = ""
            if not s:
                if entry:
                    break
                else:
                    continue
            s = s.split("=")
            if len(s) != 2:
                print(s)
                exit(1)
            key = s[0].strip()
            val = s[1].strip()
            if key =="len":
                try:
                    lo, hi = map(float, val.split('-'))  # validation only
                except:
                    print(key, val)
                    exit(1) 
            
            if key == "$taxon":
                taxon = val
            else:
                if key == "Lead":
                    it_no=lead_sep.split(val)
                    it=int(it_no[0])
                    no=int(it_no[1])
                    entry[key] = (taxon.split()[0], it, no)
                else:
                    entry[key] = val
        else:
            eof = True
        
        if len(entry) > 0:
            nm, it, no = entry["Lead"]
            if it < no:
                if "diag" in entry:
                    if taxon == "Carabidae":
                        genus = entry["diag"].strip(".")
                        entry["yes"] = (genus, 1)
                else: 
                    entry["yes"] = (nm, it+1)
                entry["no"]  = (nm, no)
            elif it > no:
                if "diag" in entry:
                    if taxon == "Carabidae":
                        genus = entry["diag"].strip(".")
                        entry["yes"] = (genus, 1)
                else: 
                    entry["yes"] = (nm, it+1)
            keybook.append(entry)
            entry = {}

    src.close()

    if mode == "chars":
        dissoc = []
        for i in keybook:
            if "Lead" in i:
                lead=i["Lead"]
            else:
                lead=""
            for key in i.keys():
                if key == "Lead":
                    continue
                else:
                    dissoc.append([key, i[key], lead])
        dissoc.sort()
        for i in dissoc:
          print(i[0], i[1], i[2])
    elif mode == "pages":
        keyset = {}
        for i in keybook:
            if "Lead" in i:
                keyset[i["Lead"][0:2]] = i
            else:
                error("Missing Lead attribute")
        for k, v in keyset.items():
            print (k, v, '\n')
        traverse(keyset, ("Carabidae", 1), [])

main()

